package spark.utility;

/**
 * This class serves the purpose to measure how much time elapsed between two frames
 * and aids other modules to perform update operations which are time-based.
 */
public class Clock {
	private static Clock instance = new Clock();

	//Timing logic
	private long elapsedTickCount;
	private long lastTickCount;
	private long ticksThisSecond;
	private static final float TICKS_PER_SECOND = 1000.0f;
	private static final float MILLISECONDS_PER_SECOND = 1000.0f;
	private double elapsedTickCountTotal;

	//FPS logic
	private long framesLastSecond;
	private long framesThisSecond;

	public Clock() {
		reset();
	}

	public void reset() {
		lastTickCount = getCurrentTickCount();
		elapsedTickCount = 0;
		ticksThisSecond = 0;
		framesLastSecond = 0;
		framesThisSecond = 0;
		elapsedTickCountTotal = 0;
	}

	public void update() {
		long currentTickCount = getCurrentTickCount();

		elapsedTickCount = currentTickCount - lastTickCount;
		elapsedTickCountTotal += elapsedTickCount;
		lastTickCount = currentTickCount;

		ticksThisSecond += elapsedTickCount;
		++framesThisSecond;

		if(ticksThisSecond >= TICKS_PER_SECOND) {
			framesLastSecond = framesThisSecond;
			framesThisSecond = 0;
			ticksThisSecond = 0;
		}
	}

	public float getElapsedMilliseconds() {
		return ((float) elapsedTickCount);
	}

	public float getElapsedMillisecondsTotal() {
		return ((float) elapsedTickCountTotal);
	}

	public float getElapsedSeconds() {
		return ((float) elapsedTickCount / TICKS_PER_SECOND);
	}

	public float getElapsedSecondsTotal() {
		return ((float) elapsedTickCountTotal / TICKS_PER_SECOND);
	}

	public long getFramesPerSecond() {
		return framesLastSecond;
	}

	private long getCurrentTickCount() {
		return System.currentTimeMillis();
	}

	public static Clock getInstance() {
		return instance;
	}

	public static String secondsToString(float seconds) {
		return milliSecondsToString((long) (seconds * 1000));
	}

	public static String milliSecondsToString(long milliSeconds) {
		int msPart = (int) (milliSeconds % 1000);
		int secondsPart = (int) ((milliSeconds / 1000) % 60);
		int minutesPart = (int) ((milliSeconds / 1000 * 60) % 60);
		int hoursPart = (int) ((milliSeconds / 1000 * 60 * 60) % 24);
		String hundredthSecondsStr = Integer.toString((msPart / 100));
		String secondsStr = (secondsPart < 10 ? "0" : "") + secondsPart;
		String minutesStr = (minutesPart < 10 ? "0" : "") + minutesPart;
		String hoursStr = (hoursPart < 10 ? "0" : "") + hoursPart;
		return minutesStr + ":" + secondsStr + ":" + hundredthSecondsStr;
	}
}
